﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using PaperCut.Classes;

namespace PaperCut
{
    public partial class SmoothPath : Path
    {
        public SmoothPath(Geometry data)
        {
            InitializeComponent();

            this.Data = data;



         
            pbs = new List<System.Windows.Point>();
        }

        List<System.Windows.Point> pbs = new List<System.Windows.Point>();

        PathGeometry pathGeometry;
        PathFigure pathFigure;
        bool pathIsClear = true;
        private void Init()
        {
            pathGeometry = new PathGeometry();
            pathFigure = new PathFigure();
            pathFigure.IsFilled = false;
            pathGeometry.Figures.Add(pathFigure);
            this.Data = pathGeometry;
            pathIsClear = true;
        }

        public void AddPoint(Point P)
        {
            if (pathIsClear)
            {
                pathFigure.StartPoint = P;
                pathIsClear = false;
                return;
            }

            if (pathFigure.Segments.Count == 0)
            {

                if (pbs.Count == 0)
                {
                    pbs.Add(P);
                }
                else if (pbs.Count == 1)
                {
                    pbs.Add(P);

                    QuadraticBezierSegment bs = new QuadraticBezierSegment();
                    bs.Point1 = pbs[0];
                    bs.Point2 = pbs[1];


                    pathFigure.Segments.Add(bs);
                    System.Windows.Point tmp = pbs[1];
                    pbs = new List<System.Windows.Point>();
                    pbs.Add(tmp);
                }

            }
            else
            {
                pbs.Add(P);

                QuadraticBezierSegment last = (QuadraticBezierSegment)pathFigure.Segments.Last();
                System.Windows.Point tmp2 = last.Point2;
                last.Point2 = GeometryHelper.LineMiddle(last.Point1, last.Point2);

                QuadraticBezierSegment bs = new QuadraticBezierSegment();
                bs.Point1 = pbs[0];
                bs.Point2 = pbs[1];

                pathFigure.Segments.Add(bs);
                System.Windows.Point tmp = pbs[1];
                pbs = new List<System.Windows.Point>();
                pbs.Add(tmp);
            }



            this.Opacity = 0.99;
            this.Opacity = 1;

        }

        double GetPathLength(PathFigure path)
        {
            double len = 0.0;
            Point A = path.StartPoint;
            foreach (PathSegment ps in path.Segments)
            {
                switch (ps.GetType().Name)
                {
                    case "BezierSegment":
                        var cbseg = (BezierSegment)ps;
                        len += BezierHelper.GetCubicBezierLength(A, cbseg.Point1, cbseg.Point2, cbseg.Point3);
                        break;
                    case "QuadraticBezierSegment":
                        var qbseg = (QuadraticBezierSegment)ps;
                        len += BezierHelper.GetQuadraticBezierLength(A, qbseg.Point1, qbseg.Point2);
                        break;
                    case "LineSegment":
                        var lseg = (LineSegment)ps;
                        len += GeometryHelper.GetLineLength(A, lseg.Point);
                        break;
                }
            }
            return len;
        }

        int GetPathSegmentAtLength(PathFigure path, double d)
        {
            double len = 0.0;
            Point A = path.StartPoint;
            int i = 0;
            foreach (PathSegment ps in path.Segments)
            {
                switch (ps.GetType().Name)
                {
                    case "BezierSegment":
                        var cbseg = (BezierSegment)ps;
                        len += BezierHelper.GetCubicBezierLength(A, cbseg.Point1, cbseg.Point2, cbseg.Point3);
                        break;
                    case "QuadraticBezierSegment":
                        var qbseg = (QuadraticBezierSegment)ps;
                        len += BezierHelper.GetQuadraticBezierLength(A, qbseg.Point1, qbseg.Point2);
                        break;
                    case "LineSegment":
                        var lseg = (LineSegment)ps;
                        len += GeometryHelper.GetLineLength(A, lseg.Point);
                        break;
                }
                if (d <= len) return i;
                i++;

            }
            return -1;
        }
        List<Point> ToPolygon(PathFigure path, int samples)
        {
            double totalLen = GetPathLength(path);
            double step = totalLen / samples;

            double len, currentLen = 0;
            Point A = path.StartPoint;
            int i = 0;
            double d = 0;

            List<Point> points = new List<Point>();
            foreach (PathSegment ps in path.Segments)
            {
                switch (ps.GetType().Name)
                {
                    case "BezierSegment":
                        var cbseg = (BezierSegment)ps;

                        len = BezierHelper.GetCubicBezierLength(A, cbseg.Point1, cbseg.Point2, cbseg.Point3);
                        while (d < currentLen + len)
                        {
                            double t = (d - currentLen) / len;
                            points.Add(BezierHelper.GetCubicBezierPointAt(t, A, cbseg.Point1, cbseg.Point2, cbseg.Point3));

                            d += step;
                        }
                        currentLen += len;
                        A = cbseg.Point3;

                        break;
                    case "QuadraticBezierSegment":
                        var qbseg = (QuadraticBezierSegment)ps;
                        len = BezierHelper.GetQuadraticBezierLength(A, qbseg.Point1, qbseg.Point2);
                        while (d < currentLen + len)
                        {
                            double t = (d - currentLen) / len;
                            points.Add(BezierHelper.GetQuadraticBezierPointAt(t, A, qbseg.Point1, qbseg.Point2));

                            d += step;
                        }
                        currentLen += len;
                        A = qbseg.Point2;

                        break;
                    case "LineSegment":
                        var lseg = (LineSegment)ps;
                        len = GeometryHelper.GetLineLength(A, lseg.Point);
                        while (d < currentLen + len)
                        {
                            double t = (d - currentLen) / len;
                            points.Add(GeometryHelper.GetLinePointAt(t, A, lseg.Point));

                            d += step;
                        }
                        currentLen += len;
                        A = lseg.Point;
                        break;
                }
            }
            return points;
        }

        
    }
}
